package com.gamefx.mvc
{
	import flash.utils.describeType;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getQualifiedSuperclassName;


	internal class Injector
	{
		private var facade:Facade = Facade.getInstance() as Facade;
		private var CLASS_NAME_MODEL:String;
		private var CLASS_NAME_VIEW:String;

		public function Injector()
		{
			CLASS_NAME_MODEL = Facade.Name(Model);
			CLASS_NAME_VIEW = Facade.Name(View);
		}

		public function inject(obj:Object):Object
		{
			var info:XML = describeType(Class(getDefinitionByName(getQualifiedClassName(obj))));
			var node:XML;

			var propertyName:String;
			var propertyType:String;
			var requestName:String;

			for each (node in info.factory.*.(name() == 'variable' || name() == 'accessor').metadata.(@name == 'Inject'))
			{
				propertyName = node.parent().@name.toString();
				propertyType = node.parent().@type.toString();
				requestName = node.arg.attribute('value').toString();

				obj[propertyName] = getResponse(propertyType, requestName);
			}

			return obj;
		}
		
		public function subscribe(obj:Object):Object
		{
			var info:XML = describeType(Class(getDefinitionByName(getQualifiedClassName(obj))));
			
			var node:XML;
			var methodName:String;
			var requestName:String;

			for each (node in info.factory.method.metadata.(@name == 'Subscribe'))
			{
				methodName = node.parent().@name.toString();
				requestName = node.arg.attribute('value').toString();
				
				(obj as View).subscribe(requestName, obj[methodName]);
			}
			
			return obj;
		}

		private function getResponse(className:String, requestName:String = ''):Object
		{
			var map:Object;
			var superClassName:String = getQualifiedSuperclassName(getDefinitionByName(className)).replace("::", ".");

			switch (superClassName)
			{
				case CLASS_NAME_MODEL:
					map = facade.modelMap;
					break;

				case CLASS_NAME_VIEW:
					map = facade.modelMap;
					break;
			}

			if (map != null)
			{
				requestName = (requestName != '') ? requestName : className.replace("::", ".");

				if (requestName in map)
				{
					return map[requestName];
				}
			}

			return null;
		}


	}
}
